#include "minimusic.h"
#include "ui_minimusic.h"

MiniMusic::MiniMusic(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MiniMusic)
    ,currentIndex(-1)
{
    ui->setupUi(this);

    this->initUI();
    initSQLite();
    // 加载数据库歌曲⽂件
    initMusicList();

    initPlayer();
    //建立页面切换信号与槽的连接
    connectSignalAndSlot();
}

MiniMusic::~MiniMusic()
{
    delete ui;
}

void MiniMusic::initPlayer()
{
    // 创建播放器
    player = new QMediaPlayer(this);
    // 创建播放列表
    playList = new QMediaPlaylist(this);
    // 设置播放模式：默认为循环播放
    playList->setPlaybackMode(QMediaPlaylist::Loop);
    // 将播放列表设置给播放器
    player->setPlaylist(playList);
    // 默认⾳量⼤⼩设置为20
    player->setVolume(20);
    connect(player, &QMediaPlayer::stateChanged, this,&MiniMusic::onPlayStateChanged);
    connect(playList, &QMediaPlaylist::currentIndexChanged, this,&MiniMusic::onCurrentIndexChanged);
    connect(playList, &QMediaPlaylist::playbackModeChanged, this,&MiniMusic::onPlaybackModeChanged);
    //播放时长
    connect(player, &QMediaPlayer::durationChanged, this,&MiniMusic::onDurationChanged);
    connect(player, &QMediaPlayer::positionChanged, this,&MiniMusic::onPositionChanged);
}

void MiniMusic::initUI()
{
    setWindowFlag(Qt::WindowType::FramelessWindowHint);
    // 设置窗⼝背景透明
    this->setAttribute(Qt::WA_TranslucentBackground);
    setWindowIcon(QIcon(":/image/tubiao.png")); // 设置主窗⼝图标
    // 给窗⼝设置阴影效果
    QGraphicsDropShadowEffect* shadowEffect = new
    QGraphicsDropShadowEffect(this);
    shadowEffect->setOffset(0,0); // 设置阴影偏移
    shadowEffect->setColor("#000000"); // 设置阴影颜⾊：⿊⾊
    shadowEffect->setBlurRadius(10); // 设置阴影的模糊半径
    this->setGraphicsEffect(shadowEffect);

    // 设置BodyLeft中6个btForm的信息
    ui->Rec->seticon(":/image/rec.png", "推荐", 1);
    ui->music->seticon(":/image/music.png", "⾳乐馆", 2);
    ui->audio->seticon(":/image/radio.png", "电台", 3);
    ui->like->seticon(":/image/like.png", "我喜欢", 4);
    ui->local->seticon(":/image/local.png", "本地下载", 5);
    ui->recent->seticon(":/image/recent.png", "最近播放", 6);

    // 将localPage设置为当前⻚⾯
    ui->stackedWidget->setCurrentIndex(4);
    curPage = ui->localPage;



    //推荐页面初始化
    srand(time(NULL));
    ui->recMusicBox->initRecBoxUi(RandomPicture(),1);
    ui->supplyMusicBox->initRecBoxUi(RandomPicture(),2);

    //初始化commonpage
    ui->likePage->setCommonPageUI("我喜欢", ":/image/ilikebg.png");
    ui->localPage->setCommonPageUI("本地⾳乐", ":/image/localbg.png");
    ui->recentPage->setCommonPageUI("最近播放", ":/image/recentbg.png");

    //音量弹出窗口初始化
    volumeTool = new VolumeTool(this);

    // 设置CommonPage的信息
    ui->likePage->setMusicListType(PageType::LIKE_PAGE);
    ui->likePage->setCommonPageUI("我喜欢", ":/image/ilikebg.png");
    ui->localPage->setMusicListType(PageType::LOCAL_PAGE);
    ui->localPage->setCommonPageUI("本地⾳乐", ":/image/localbg.png");
    ui->recentPage->setMusicListType(PageType::HISTORY_PAGE);
    ui->recentPage->setCommonPageUI("最近播放", ":/image/recentbg.png");

    // 按钮的背景图⽚样式去除掉之后，需要设置默认图标
    // 播放控制区按钮图标设定
    ui->play->setIcon(QIcon(":/image/play_2.png")); // 默认为暂停图标
    ui->playMode->setIcon(QIcon(":/image/shuffle_2.png")); // 默认为随机播放
    volumeTool = new VolumeTool(this);

    // 实例化LrcWord对象
    lrcPage = new LrcPage(this);
    lrcPage->hide();
    // lrcPage添加动画效果
    lrcAnimation = new QPropertyAnimation(lrcPage, "geometry", this);
    lrcAnimation->setDuration(250);
    lrcAnimation->setStartValue(QRect(10, 10+lrcPage->height(),
    lrcPage->width(), lrcPage->height()));
    lrcAnimation->setEndValue(QRect(10, 10, lrcPage->width(), lrcPage->height()));




}

void MiniMusic::onUpdateLikeMusic(bool isLike, QString musicId)
{
    // 1. 找到该⾸歌曲，并更新对应Music对象信息
    auto it = musicList.findMusicById(musicId);
    if(it != musicList.end())
    {
    it->setIsLike(isLike);
    }
    // 2. 通知三个⻚⾯更新⾃⼰的数据
    ui->likePage->reFresh(musicList);
    ui->localPage->reFresh(musicList);
    ui->recentPage->reFresh(musicList);
}

void MiniMusic::mousePressEvent(QMouseEvent *event)
{
    if(event->button()==Qt::LeftButton){
        dragPosition=event->globalPos()-frameGeometry().topLeft();//窗口左上角与光标的距离差（鼠标按下时）frameGeometry包括了边框和标题
        return;
    }
    mousePressEvent(event);
}

void MiniMusic::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons()==Qt::LeftButton){
        move(event->globalPos()-dragPosition);
        return;
    }
    mouseMoveEvent(event);
}

void MiniMusic::onBtFormClick(int id)
{
    // 1.获取当前⻚⾯所有btFrom按钮类型的对象
    QList<btForm*> buttonList = this->findChildren<btForm*>();
    // 2.遍历所有对象, 如果不是当前id的按钮,则把之前设置的背景颜⾊清除掉
    foreach (btForm* btitem, buttonList)
    {
        if (id != btitem->getId())
        {
                btitem->clearBg();
                btitem->stopAnimal();

        }
    }
    // 3.设置当前栈空间显⽰⻚⾯
    ui->stackedWidget->setCurrentIndex(id-1);
}

void MiniMusic::connectSignalAndSlot()
{
    //按钮槽
    connect(ui->Rec, &btForm::btClick, this, &MiniMusic::onBtFormClick);
    connect(ui->music, &btForm::btClick, this, &MiniMusic::onBtFormClick);
    connect(ui->audio,&btForm::btClick, this, &MiniMusic::onBtFormClick);
    connect(ui->like, &btForm::btClick, this, &MiniMusic::onBtFormClick);
    connect(ui->local,&btForm::btClick, this, &MiniMusic::onBtFormClick);
    connect(ui->recent,&btForm::btClick, this, &MiniMusic::onBtFormClick);
    //页
    connect(ui->likePage, &Common::updateLikeMusic, this,&MiniMusic::onUpdateLikeMusic);
    connect(ui->localPage, &Common::updateLikeMusic, this,&MiniMusic::onUpdateLikeMusic);
    connect(ui->recentPage, &Common::updateLikeMusic, this,&MiniMusic::onUpdateLikeMusic);


    connect(ui->likePage, &Common::playAll, this, &MiniMusic::onPlayAll);
    connect(ui->localPage, &Common::playAll, this, &MiniMusic::onPlayAll);
    connect(ui->recentPage, &Common::playAll, this, &MiniMusic::onPlayAll);

    // 处理likePage、localPage、recentPage中ListItemBox双击
    connect(ui->likePage, &Common::playMusicByIndex, this,&MiniMusic::playMusicByIndex);
    connect(ui->localPage, &Common::playMusicByIndex, this,&MiniMusic::playMusicByIndex);
    connect(ui->recentPage, &Common::playMusicByIndex, this,&MiniMusic::playMusicByIndex);

    // 设置静⾳
    connect(volumeTool, &VolumeTool::setSilence, this,&MiniMusic::setMusicSilence);
    //音量设置
   connect(volumeTool, &VolumeTool::setMusicVolume, this,&MiniMusic::setPlayerVolume);
    //进度条
    bool a =connect(ui->processBar, &MusicSlider::setMusicSliderPosition, this,&MiniMusic::onMusicSliderChanged);
    if (!a) {
        qDebug() << "a！";
    }
    // 关联QMediaPlayer::metaDataAvailableChanged
   bool isConnected = connect(player, &QMediaPlayer::metaDataAvailableChanged, this, &MiniMusic::onMetaDataAvailableChanged);

   if (!isConnected) {
       qDebug() << "信号与槽连接失败！";
   }
}

QJsonArray MiniMusic::RandomPicture()
{
    QVector<QString> vecImageName;
    vecImageName<<"001.png"<<"003.png"<<"004.png"<<"005.png"<<"006.png"
    <<"007.png"
    <<"008.png"<<"009.png"<<"010.png"<<"011.png"<<"012.png"
    <<"013.png"
    <<"014.png"<<"015.png"<<"016.png"<<"017.png"<<"018.png"
    <<"019.png"
    <<"020.png"<<"021.png"<<"022.png"<<"023.png"<<"024.png"
    <<"025.png"
    <<"026.png"<<"027.png"<<"028.png"<<"029.png"<<"030.png"
    <<"031.png"
    <<"032.png"<<"033.png"<<"034.png"<<"035.png"<<"036.png"
    <<"037.png"
    <<"038.png"<<"039.png"<<"040.png";
    std::random_shuffle(vecImageName.begin(), vecImageName.end());
    // 001.png
    // path: ":/image/rec/"+vecImageName[i];
    // text: "推荐-001"
    QJsonArray objArray;
    for(int i = 0; i < vecImageName.size(); ++i)
    {
    QJsonObject obj;
    obj.insert("path", ":/image/rec/"+vecImageName[i]);
    // arg(i, 3, 10, QCchar('0'))
    // i：要放⼊%1位置的数据
    // 3: 三位数
    // 10：表⽰⼗进制数
    // QChar('0')：数字不够三位，前⾯⽤字符'0'填充
    QString strText = QString("推荐-%1").arg(i, 3, 10, QChar('0'));
    obj.insert("text", strText);
    objArray.append(obj);
    }
    return objArray;
}

void MiniMusic::onPlayStateChanged()
{
    qDebug()<<"播放状态改变";
    if(player->state() == QMediaPlayer::PlayingState)
    {
    // 播放状态
        ui->play->setIcon(QIcon(":/image/play_on.png"));
    }
    else
    {
    // 暂停状态
        ui->play->setIcon(QIcon(":/image/play3.png"));
    }
}

void MiniMusic::onPlaybackModeChanged(QMediaPlaylist::PlaybackMode playbackMode)
{
    if(playbackMode == QMediaPlaylist::Loop)
    {
        ui->playMode->setIcon(QIcon(":/image/list_play.png"));
    }
    else if(playbackMode == QMediaPlaylist::Random)
    {
        ui->playMode->setIcon(QIcon(":/image/shuffle_2.png"));
    }
    else if(playbackMode == QMediaPlaylist::CurrentItemInLoop)
    {
        ui->playMode->setIcon(QIcon(":/image/single_play.png"));
    }
    else
    {
    qDebug()<<"暂不⽀持该模式";
    }
}

void MiniMusic::onPlayAll(PageType pageType)
{
    Common* page = nullptr;
    switch(pageType)
    {
    case PageType::LIKE_PAGE:
    page = ui->likePage;
    break;
    case PageType::LOCAL_PAGE:
    page = ui->localPage;
    break;
    case PageType::HISTORY_PAGE:
    page = ui->recentPage;
    break;
    default:
    qDebug()<<"扩展";
    }
    // 从当前⻚⾯的零号位置开始播放
    playAllOfCommonPage(page, 0);
}

void MiniMusic::playAllOfCommonPage(Common *commonPage, int index)
{
    // 播放page所在⻚⾯的⾳乐
    // 将播放列表先清空，否则⽆法播放当前CommonPage⻚⾯的歌曲
    // 另外：该⻚⾯⾳乐不⼀定就在播放列表中，因此需要先将该⻚⾯⾳乐添加到播放列表
    curPage=commonPage;
    playList->clear();
    // 将当前⻚⾯歌曲添加到播放列表
   commonPage->addMusicToPlayer(musicList, playList);
    // 设置当前播放列表的索引
    playList->setCurrentIndex(index);
    // 播放
    player->play();
}

void MiniMusic::onCurrentIndexChanged(int index)
{
     currentIndex = index;
    // ⾳乐的id都在commonPage中的musicListOfPage中存储着
    const QString& musicId = curPage->getMusicIdByIndex(index);
    // 有了MusicId就可以再musicList中找到该⾳乐
    auto it =  musicList.findMusicById(musicId);
    if(it != musicList.end())
    {
    // 将该⾳乐设置为历史播放记录
    it->setIsHistory(true);
    }
    ui->recentPage->reFresh(musicList);
}

void MiniMusic::setMusicSilence(bool isMuted)
{
    player->setMuted(isMuted);
}

void MiniMusic::setPlayerVolume(int volume)
{
    player->setVolume(volume);
}

void MiniMusic::onDurationChanged(qint64 duration)
{
    // duration为歌曲的总时长,单位为毫秒
    // 需要将整形的总时长转换为min:sec
    // 分：duration/1000/60;
    // 秒：duration/1000%60;
    totalTime=duration;
    ui->totalTime->setText(QString("%1:%2").arg(duration/1000/60, 2, 10,
    QChar('0'))
    .arg(duration/1000%60,2,10,
         QChar('0')));
}

void MiniMusic::onPositionChanged(qint64 duration)
{
    // qqmusic.cpp 中新增

    ui->currentTime->setText(QString("%1:%2").arg(duration/1000/60, 2, 10,
            QChar('0'))
            .arg(duration/1000%60,2,10,
            QChar('0')));
            // 2. 进度条处理

    // 界⾯上的进度条也需要同步修改
    ui->processBar->setStep((float)duration / (float)totalTime);

    // 3. 同步lrc歌词
    if(playList->currentIndex() >= 0)
    {
    lrcPage->showLrcWord(duration);
    }
}

void MiniMusic::onMusicSliderChanged(float value)
{
    // 1. 计算当前seek位置的时⻓
    qint64 duration = totalTime* value;
    ui->currentTime->setText(QString("%1:%2").arg(duration/1000/60, 2, 10, QChar('0'))
                                             .arg(duration/1000%60, 2, 10, QChar('0')));
    qDebug()<<duration;
    // 3. 设置当前播放位置
    player->setPosition(duration);
}

void MiniMusic::onMetaDataAvailableChanged(bool available)
{
    if (!available); // 元数据不可用时直接返回

        qDebug() << "歌曲切换";

        // 从播放器元数据获取歌曲信息
        QString singer = player->metaData("Author").toStringList().join(",");
        QString musicName = player->metaData("Title").toString();

        auto it = musicList.findMusicById(curPage->getMusicIdByIndex(currentIndex));
        // 如果元数据中没有歌曲名，则从音乐列表查找
        if (musicName.isEmpty())
        {

            if (it != musicList.end())
            {
                musicName = it->getMusicName();
                singer = it->getSingerName();
            }
            else
            {
                qDebug() << "未在音乐列表中找到歌曲信息";
                musicName = "未知歌曲";
                singer = "未知歌手";
            }
        }

        // 更新UI显示
        ui->musicName->setText(musicName);
        ui->musicSinger->setText(singer);

        // 处理封面图片
        QVariant coverImage = player->metaData("ThumbnailImage");
        QPixmap coverPixmap;

        if (coverImage.isValid())
        {
            // 使用元数据中的封面图
            QImage image = coverImage.value<QImage>();
            coverPixmap = QPixmap::fromImage(image);
        }
        else
        {
            // 使用默认封面图
            qDebug() << "歌曲没有封面图片，使用默认图片";
            coverPixmap = QPixmap(":/image/rec/001.png");
        }

        // 设置封面图并启用缩放
        ui->musicCover->setPixmap(coverPixmap);
        ui->musicCover->setScaledContents(true);
        curPage->setImageLabel(coverPixmap);
        // 加载lrc歌词并解析
        if(it != musicList.end())
        {
        lrcPage->parseLrc(it->getLrcFilePath());
        }
}

void MiniMusic::playMusicByIndex(Common *page, int index)
{
    playAllOfCommonPage(page, index);
}

void MiniMusic::initMusicList()
{
    // 1. 从数据库读取歌曲信息
    musicList.readFromDB();
    // 2. 更新CommonPage⻚⾯
    // 设置CommonPage的信息
    ui->likePage->setMusicListType(PageType::LIKE_PAGE);
    ui->likePage->reFresh(musicList);
    ui->localPage->setMusicListType(PageType::LOCAL_PAGE);
    ui->localPage->reFresh(musicList);
    ui->recentPage->setMusicListType(PageType::HISTORY_PAGE);
    ui->recentPage->reFresh(musicList);
}

void MiniMusic::initSQLite()
{
    // 1. 创建数据库连接
    sqlite = QSqlDatabase::addDatabase("QSQLITE");
    // 2. 设置数据库名称
    sqlite.setDatabaseName("MiniMusic.db");
    // 3. 打开数据库
    if(!sqlite.open())
    {
        QMessageBox::critical(this, "打开QQMusicDB失败",
        sqlite.lastError().text());
        return;
     }
    qDebug()<<"SQLite连接成功，并创建 [MiniMusic.db] 数据库!!!";
    // 4. 创建数据库表
    QString sql = ("CREATE TABLE IF NOT EXISTS musicInfo(\
    id INTEGER PRIMARY KEY AUTOINCREMENT,\
    musicId varchar(200) UNIQUE,\
    musicName varchar(50),\
    singerName varchar(50),\
    albumName varchar(50),\
    duration BIGINT,\
    musicUrl varchar(256),\
    isLike INTEGER,\
    isHistory INTEGER)"
    );
    QSqlQuery query;
    if(!query.exec(sql))
    {
        QMessageBox::critical(this, "创建数据库表失败",
        query.lastError().text());
        return;
    }
    qDebug()<<"创建 [musicInfo] 表成功!!!";

}



void MiniMusic::on_volume_clicked()
{
    // 先要调整窗⼝的显⽰位置，否则该窗⼝在主窗⼝的左上⻆
    // 1. 获取该按钮左上⻆的图标
    QPoint point = ui->volume->mapToGlobal(QPoint(0,0));
    // 2. 计算volume窗⼝的左上⻆位置
    // 让该窗⼝显⽰在⿏标点击的正上⽅
    // ⿏标位置：减去窗⼝宽度的⼀半，以及⾼度恰巧就是窗⼝的左上⻆
    QPoint volumeLeftTop = point - QPoint(volumeTool->width()/2, volumeTool->height());
    // 微调窗⼝位置
    volumeLeftTop.setY(volumeLeftTop.y()+30);
    volumeLeftTop.setX(volumeLeftTop.x()+15);
    // 3. 移动窗⼝位置
    volumeTool->move(volumeLeftTop);
    // 4. 将窗⼝显⽰出来
    volumeTool->show();
}

void MiniMusic::on_addlocal_clicked()
{
    // 1. 创建⼀个⽂件对话框
    QFileDialog fileDialog(this);
    fileDialog.setWindowTitle("添加本地⾳乐");
    // 2. 创建⼀个打开格式的⽂件对话框
    fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
    // 3. 设置对话框模式
    // 只能选择⽂件，并且⼀次性可以选择多个存在的⽂件
    fileDialog.setFileMode(QFileDialog::ExistingFiles);
    // 4. 设置对话框的MIME过滤器
    QStringList mimeList;
    mimeList<<"application/octet-stream";
    fileDialog.setMimeTypeFilters(mimeList);
    // 5. 设置对话框默认的打开路径,设置⽬录为当前⼯程所在⽬录
    QDir dir(QDir::currentPath());
    dir.cdUp();
    QString musicPath = dir.path()+"/MninMusic/musics/";
    fileDialog.setDirectory(musicPath);
    // 6. 显⽰对话框，并接收返回值
    // 模态对话框, exec内部是死循环处理
    if(fileDialog.exec() == QFileDialog::Accepted)
    {
        // 切换到本地⾳乐界⾯，因为加载完的⾳乐需要在本地⾳乐界⾯显⽰
        ui->stackedWidget->setCurrentIndex(4);
        // 获取对话框的返回值
        QList<QUrl> urls = fileDialog.selectedUrls();
        // 注意：后序需要将⾳乐信息添加到数据库，否则每次打开是都需要添加⾳乐太⿇烦了
        musicList.addMusicByUrl(urls);
        // 更新到本地⾳乐列表
        ui->localPage->reFresh(musicList);
    }
}



void MiniMusic::on_play_clicked()
{
    qDebug()<<"播放按钮点击";
    if(player->state() == QMediaPlayer::PlayingState){
    // 如果是歌曲正在播放中，按下播放键，此时应该暂停播放
        player->pause();
    }
    else if(player->state() == QMediaPlayer::PausedState)
    {
    // 如果是暂停状态，按下播放键，继续开始播放
        player->play();
    }
    else if(player->state() == QMediaPlayer::StoppedState)
    {
        player->play();
    }
}

void MiniMusic::on_playUp_clicked()
{
    playList->previous();
}

void MiniMusic::on_playDown_clicked()
{
    playList->next();
}

void MiniMusic::on_playMode_clicked()
{
    // 播放模式是针对播放列表的
    // 播放模式⽀持：循环播放、随机播放、单曲循环三种模式
    if(playList->playbackMode() == QMediaPlaylist::Loop)
    {
        // 列表循环
        ui->playMode->setToolTip("随机播放");
        playList->setPlaybackMode(QMediaPlaylist::Random);
    }
    else if(playList->playbackMode() == QMediaPlaylist::Random)
    {
        // 随机播放
        ui->playMode->setToolTip("单曲循环");
        playList->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
    }
    else if(playList->playbackMode() == QMediaPlaylist::CurrentItemInLoop)
    {
         ui->playMode->setToolTip("列表循环");
         playList->setPlaybackMode(QMediaPlaylist::Loop);
    }
    else
    {
    qDebug()<<"播放模式错误";
    }
}

void MiniMusic::on_lrcWord_clicked()
{
    lrcPage->show();
    lrcAnimation->start();
}



void MiniMusic::on_quit_clicked()
{
    // 更新数据库
    musicList.writeToDB();
    // 关闭数据库连接
    sqlite.close();
    // 关闭窗⼝
    close();
}
